#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

typedef int SLTDateType;
typedef struct SListNode
{
    SLTDateType data;
    struct SListNode* next;
}SListNode;

// 动态申请一个节点
SListNode *BuySListNode(SLTDateType x)
{
    SListNode *newnode = (SListNode*)malloc(sizeof(SListNode));
    if(newnode == NULL)
    {
        perror("malloc fail:");
        return NULL;
    }
    newnode->data = x;
    newnode->next = NULL;
    return newnode;
}
// 单链表打印
void SListPrint(SListNode* plist)
{
    SListNode *cur = plist;
    while(cur!=NULL)
    {
        printf("%d->",cur->data);
        cur = cur->next;
    }
    printf("NULL");
}
// 单链表尾插
void SListPushBack(SListNode** pplist, SLTDateType x)
{
    SListNode *newnode = BuySListNode(x);
    if(*pplist == NULL)
    {
        *pplist = newnode;
    }
    else
    {
        SListNode *tail = *pplist;
        while(tail->next != NULL)
        {
            tail = tail->next;
        }
        tail->next = newnode;
    }
}

// 单链表的头插
void SListPushFront(SListNode** pplist, SLTDateType x)
{
    SListNode *newnode = BuySListNode(x);
    newnode->next = *pplist;
    *pplist = newnode;
}
// 单链表的尾删
void SListPopBack(SListNode** pplist)
{
    assert(pplist);
    assert(*pplist);
    if((*pplist)->next == NULL)
    {
        free(*pplist);
        *pplist = NULL;
    }
    else
    {
        SListNode *prev = NULL;
        SListNode *tail = *pplist;
        while(tail->next !=NULL)
        {
            prev = tail;
            tail = tail->next;
        }
        free(tail);
        tail = NULL;
        prev->next = NULL;
    }
}
// 单链表头删
void SListPopFront(SListNode** pplist)
{
    assert(pplist);
    SListNode *first = *pplist;
    *pplist = first->next;
    free(first);
    first = NULL;
}
// 单链表查找
SListNode* SListFind(SListNode* plist, SLTDateType x)
{
    SListNode *cur = plist;
    while(cur != NULL)
    {
        if(cur->data == x)
        {
            return cur;
        }
        else
        {
            cur = cur->next;
        }
    }
    return NULL;
}

// 分析思考为什么不在pos位置之前插入？
// 答：需要pos前的next指向插入的newnode，但pos前一个位置只能从头才能找到。
// 单链表在pos位置之后插入x。
void SListInsertAfter(SListNode* pos, SLTDateType x)
{
    assert(pos);
    SListNode *newnode = BuySListNode(x);
    newnode->next = pos->next;
    pos->next = newnode;
}

// 分析思考为什么不删除pos位置？答：同理需要找到pos前一个位置
// 单链表删除pos位置之后的值
void SListEraseAfter(SListNode* pos)
{
    assert(pos);
    assert(pos->next);

    SListNode *del = pos->next;
    pos->next = del->next;
    free(del);
    del = NULL;
}

// 在pos的前面插入
void SLTInsert(SListNode** pphead, SListNode* pos, SLTDateType x)
{
    assert(pos);
    assert(*pphead);

    if(pos == *pphead)
    {
        SListPushFront(pphead, x);
    }
    else
    {
        SListNode *prev = *pphead;
        while (prev->next != pos)
        {
            prev = prev->next;
        }
        SListNode *newnode = BuySListNode(x);
        prev->next = newnode;
        newnode->next = pos;
    }
}
// 删除pos位置
void SLTErase(SListNode** pphead, SListNode* pos)
{
    assert(pphead);
    assert(pos);

    if(*pphead == NULL)
    {
        SListPopFront(pphead);
    }
    else
    {
        SListNode *prev = *pphead;
        while(prev->next != pos)
        {
            prev = prev->next;
        }

        prev->next = pos->next;
        free(pos);
    }
}
void SLTDestroy(SListNode *phead)
{
    SListNode *cur = phead;
    while(cur != NULL)
    {
        SListNode *tmp = cur->next;
        free(cur);
        cur = tmp;
    }
}